/**************************************************************************//**
 * @item     CosyOS-III Port
 * @file     port_cmx_iar.s
 * @brief    CMSIS Cortex-M Core Port File for IAR Compiler
 * @author   迟凯峰
 * @version  V2.0.1
 * @date     2025.11.16
 ******************************************************************************/

                                    用户须知

;     该文件是专门为 IAR-EWARM 适配的高性能移植版本，原因是 port_cmx_s.c 文件
; 虽然支持 EWARM，但对于 ARMv7-M 及以上架构来说，性能上是有少许损失的，这源于
; EWARM 内联汇编的局限性。
;     如果您的处理器架构是 ARMv7-M 或以上，并采用 EWARM 来编译您的项目，同时
; 又追求卓越性能，可移除 port_cmx_s.c 文件，并替换为该文件进行编译。
;     注意，该文件仅支持 ARMv7-M 及以上架构，mcucfg_cmx.h 中，互斥访问方案 也
; 必须选择为高性能的 互斥访问指令。

////////////////////////////////////////////////////////////////////////////////

                INCLUDE syscfg.h
                INCLUDE mcucfg_cm0.h
                INCLUDE mcucfg_cm3.h

                SECTION .text:CODE:REORDER:NOROOT(2)
                THUMB

////////////////////////////////////////////////////////////////////////////////

; PendSV软中断

                PUBLIC  OS_PendSV_Handler
OS_PendSV_Handler:
                EXTERN  sPendSV_Handler
                EXTERN  s_task_current
                EXTERN  s_task_news
                PRESERVE8

                push    {lr}
                bl      sPendSV_Handler
; 直接返回吗？
                cbz     r0, __RETURN
                isb
; 保护现场吗？
                ldr     r1, =s_task_current
                IF (SYSCFG_DEBUGGING == 1)
                subs    r0, #1
                cbz     r0, __RESTORE
                ENDIF
                mrs     r0, psp
; 任务PC监控
                IF (SYSCFG_TASKPC_MONITOR == 1)
                EXTERN  s_sign_taskmgr
                EXTERN  s_pc
                ldr     r2, =s_sign_taskmgr
                ldrb    r2, [r2]
                cbz     r2, __PROTECTING
                ldr     r2, [r0,#24]
                ldr     r3, =s_pc
                str     r2, [r3]
                ENDIF
; 保护现场
__PROTECTING    IF (MCUCFG_ASPEN_LSPEN == 1)
                vstmdb  r0!, {s16-s31}
                ENDIF
                stmdb   r0!, {r4-r11}
                ldr     r2, [r1]
                str     r0, [r2]
; 恢复现场
__RESTORE       ldr     r3, =s_task_news
                ldr     r3, [r3]
                str     r3, [r1]
                ldr     r0, [r3]
                ldmia   r0!, {r4-r11}
                IF (MCUCFG_ASPEN_LSPEN == 1)
                vldmia  r0!, {s16-s31}
                ENDIF
                msr     psp, r0
; 返回
__RETURN        pop     {pc}

////////////////////////////////////////////////////////////////////////////////

; 中断FIFO服务装载器

                IF (MCUCFG_PENDSVFIFO_DEPTH > 0)

                PUBLIC  mPendSV_FIFOLoader
mPendSV_FIFOLoader:
                EXTERN  mPendSV_FIFO_P0
                EXTERN  mPendSV_FIFO_P1
                EXTERN  m_sign_fifo
; FIFO选择
                ldr     r3, =m_sign_fifo
                ldrb    r3, [r3]
                cbz     r3, __FIFO1
__FIFO0         ldr     r1, =mPendSV_FIFO_P0
                b       __FIFOPTRINC
__FIFO1         ldr     r1, =mPendSV_FIFO_P1
; FIFO指针递增
__FIFOPTRINC    /* 1、互斥访问指令 */
                #if (MCUCFG_PENDSVFIFO_MUTEX == 1)
__LOOP          ldrex   r2, [r1]
                adds    r2, #4
                strex   r3, r2, [r1]
                cmp     r3, #0
                bne     __LOOP
                #else
                #error 互斥访问方案 未选择 互斥访问指令！
                #endif
; 装载
                str     r0, [r2]
                bx      lr

                ENDIF

////////////////////////////////////////////////////////////////////////////////
ALIGN
                END
